package com.tgy.util;

import org.apache.commons.lang3.StringUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.filter.RevFilter;
import org.eclipse.jgit.treewalk.TreeWalk;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author tianguiyin
 * @version 1.0
 * @date 2022/8/3 10:20
 */
public class GitHistoryUtil {

    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static String dirPath = "F:\\A-project\\tgyBlog\\.git";
    private Git git;
    private Repository repository;

    private Date begin;
    private Date end;
    private String keyword;
    private String commitName;
    private String[] keywords;

    private Set<String> commitFiles;	//依据条件查询到的提交文件记录
    private List<String> warnings;		//警告信息
    private List<String> infos;				//提交信息

    public static void main(String[] args) throws Exception {

        // Git git = Git.open(new File(dirPath));
        // git.log().call().forEach(i-> System.out.println(String.format("提交时间:%s 提交人:%s 提交备注:%s",
        //         sdf.format(new Date(i.getCommitTime() * 1000l)),i.getCommitterIdent(),i.getFullMessage())) );
        // System.out.println("---------------------------------------------------------");

        GitHistoryUtil gitHistory = new GitHistoryUtil();
        gitHistory.init();
        // gitHistory.setKeyword("增加");
        Date begin = sdf.parse("2022-06-29 08:58:24");
        gitHistory.setBegin(begin);
        Date end = sdf.parse("2022-06-29 09:54:18");
        gitHistory.setEnd(end);
        // gitHistory.setCommitName("tian_gui_yin");
        gitHistory.searchLog();
        System.out.println("-----------------commit info--------------------------");
        for(String info : gitHistory.getInfos()){
            System.out.println(info);
        }
        System.out.println("-----------------getWarning info--------------------------");
        for(String info : gitHistory.getWarnings()){
            System.out.println(info);
        }
        System.out.println("-----------------fileList info--------------------------");
        for(String file : gitHistory.commitFiles){
            System.out.println(file);
        }
    }

    public void init() throws IOException, GitAPIException {
        git = Git.open(new File(dirPath));
        repository = git.getRepository();
        this.infos = new ArrayList<>();
        this.warnings = new ArrayList<>();
        this.commitFiles = new HashSet<>();
    }

    /**
     * 验证提交记录是否满足条件
     * @param msg           提交备注
     * @param commitDate    提交时间
     * @param name          提交人
     */
    private boolean need(String msg, Date commitDate, String name) {
        boolean msgVerify = true;
        boolean dataVerify = true;
        boolean nameVerify = true;

        // 所有验证为空时表示不验证
        if (begin == null && end == null && commitName == null && keywords == null){
            return true;
        }

        // 验证备注中的关键字
        if(keywords != null){
            for (String str : keywords){
                msgVerify = StringUtils.isNotBlank(str) && msg.indexOf(str) > -1;
                if(msgVerify){
                    break;
                }
            }
        }

        // 验证开始时间
        if (begin!=null && !commitDate.after(begin)){
            dataVerify = false;
        }
        if (end!=null && !commitDate.before(end)){
            dataVerify = false;
        }

        // 验证提交人
        if (commitName!=null && !name.equals(commitName)){
            nameVerify = false;
        }

        return msgVerify&&dataVerify&&nameVerify;
    }

    /**
     * 查询提交记录
     */
    public void searchLog() throws IOException, GitAPIException {
        Iterable<RevCommit> all = git.log().setRevFilter(RevFilter.NO_MERGES).call();
        for (RevCommit revCommit : all) {
            String commitMsg = revCommit.getFullMessage();
            Date commitDate = new Date(revCommit.getCommitTime() * 1000l);
            String commitName = revCommit.getCommitterIdent().getName();

            if (need(commitMsg, commitDate ,commitName)) {
                infos.add(String.format("提交时间:%s 提交人:%s 提交备注:%s",sdf.format(commitDate),commitName,revCommit.getShortMessage()));
                // commitFiles.addAll(getConmmitFiles(revCommit));
            }
        }
    }

    /**
     * 获取提交记录提交的哪些文件
     */
    public List<String> getConmmitFiles(RevCommit commit) throws IOException, GitAPIException {
        List<String> files = new ArrayList<>();
        String commitID = commit.getName();
        if (commitID != null && !commitID.isEmpty()) {

            Date commitDate = new Date(commit.getCommitTime() * 1000l);
            TreeWalk tw = new TreeWalk(repository);
            tw.setRecursive(true);
            tw.addTree(commit.getTree());
            for (RevCommit parent : commit.getParents()) {
                tw.addTree(parent.getTree());
            }
            while (tw.next()) {
                int similarParents = 0;
                for (int i = 1; i < tw.getTreeCount(); i++) {
                    if (tw.getFileMode(i) == tw.getFileMode(0) && tw.getObjectId(0).equals(tw.getObjectId(i))) {
                        similarParents++;
                    }
                    if (similarParents == 0) {
                        String filePath = tw.getPathString();
                        files.add(filePath);
                        //记录提交的文件
                        infos.add(filePath);

                        Iterable<RevCommit> logs = git.log().addPath(filePath).setRevFilter(RevFilter.NO_MERGES).call();
                        for (RevCommit log : logs) {
                            Date logCommitDate = new Date(log.getCommitTime() * 1000l);
                            if (logCommitDate.after(commitDate)) {
                                warnings.add(String.format("提交时间:%s 提交备注:%s",sdf.format(logCommitDate),log.getShortMessage()));
                                warnings.add(filePath);
                                break;
                            }
                        }
                    }
                }
            }
            tw.close();
        }
        return files;
    }

    public void setKeyword(String keyword)
    {
        if(StringUtils.isBlank(keyword)){
            return;
        }
        this.keyword = keyword;
        keywords = StringUtils.split(keyword,",");//多个查询关键字使用,分割
    }

    public void setBegin(Date begin) {
        this.begin = begin;
    }

    public void setEnd(Date end) {
        this.end = end;
    }

    public void setDirPath(String dirPath) {
        this.dirPath = dirPath;
    }

    public Set<String> getCommitFiles() {
        return commitFiles;
    }

    public List<String> getWarnings() {
        return warnings;
    }

    public List<String> getInfos() {
        return infos;
    }

    public String getCommitName() {
        return commitName;
    }

    public void setCommitName(String commitName) {
        this.commitName = commitName;
    }
}
